#include"BlockQueue.hpp"
#include"Task.hpp"

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

const string str = "+-*/%";

void* productor(void* args)
{
  BlockQueue<Task>* bq = static_cast<BlockQueue<Task>*>(args);
  while(true)
  {
    //sleep(1);
    int x = rand() % 1000;
    int y = rand() % 1000;
    char op = str[rand() % str.size()];
    Task task(x,y,op);
    bq->push(task);
    pthread_mutex_lock(&mutex);
    cout << "Productor : " << pthread_self() << " send task to consumer : " << task.FormatArg() << endl;
    pthread_mutex_unlock(&mutex);
  }
  return nullptr;
}

void* consumer(void* args)
{
  BlockQueue<Task>* bq = static_cast<BlockQueue<Task>*>(args);
  while(true)
  {
    //sleep(1);
    Task task;
    bq->pop(task);
    task();
    pthread_mutex_lock(&mutex);
    cout << "consumer " << pthread_self() << " conduct task : " << task.FormatRes() << endl;
    pthread_mutex_unlock(&mutex);
  }
  return nullptr;
}

int main()
{
  BlockQueue<Task>* bq = new BlockQueue<Task>();
  
  srand(time(nullptr) ^ getpid());

  pthread_t c[3],p[2];
  pthread_create(&c[0],nullptr,consumer,bq);
  pthread_create(&c[1],nullptr,consumer,bq);
  pthread_create(&c[2],nullptr,consumer,bq);
  pthread_create(&p[0],nullptr,productor,bq);
  pthread_create(&p[1],nullptr,productor,bq);

  pthread_join(c[0],nullptr);
  pthread_join(c[1],nullptr);
  pthread_join(c[2],nullptr);
  pthread_join(p[0],nullptr);
  pthread_join(p[1],nullptr);

  delete bq;
  return 0;
}
